#include <iostream>
using namespace std;
#include <unistd.h>
#include <pthread.h>
#include <ctime>

struct Node
{
    /* 数据域 */
    int val;
    /* 指针域 */
    struct Node *next;
};

/* 共享数据的容器 */
Node *g_header = NULL;

/* 互斥锁 */
pthread_mutex_t g_mutex;
/* 条件变量 */
pthread_cond_t g_cond;

/* 生产者 */
void *thread_producer(void *arg)
{
    /* 线程分离 */
    pthread_detach(pthread_self());

    int cnt = 1;
    while (1)
    {
        /* 创建一个链表的节点 */
#if 0
        Node *newNode = (Node *)malloc(sizeof(Node));
        if (newNode == NULL)
        {
            perror("node error");
            continue;
        }
        newNode->val = rand() % 100;
        newNode->next = NULL;
#endif
        Node *newNode = new Node;
        newNode->val = cnt;
        newNode->next = NULL;

        /* 使用互斥锁保护共享数据 */
        pthread_mutex_lock(&g_mutex);

        /* 头插... */
        newNode->next = g_header;
        g_header = newNode;

        /* 解锁 */
        printf("producer %lu, dataId = %d\n", pthread_self(), cnt);
        pthread_mutex_unlock(&g_mutex);

        cnt++;

        /* 发条件变量 */
        pthread_cond_signal(&g_cond);

        sleep(1);
    }
    /*线程退出*/
    pthread_exit(NULL);
}
/* 消费者 */
void *thread_consumer(void *arg)
{
    /* 线程分离 */
    pthread_detach(pthread_self());
    while (1)
    {
        /* 使用互斥锁保护共享数据 */
        pthread_mutex_lock(&g_mutex);

        while (g_header == NULL)
        {
            /* 没有数据 */
            pthread_cond_wait(&g_cond, &g_mutex);
            /*
                1.解锁
                2.阻塞等待条件变量，让出CPU，不消耗CPU的时间
                3.等到条件变量被满足，立即加锁
            */
        }
        /* 程序到这个地方：有数据消费 */

        /* 头删 */
        Node *temp = g_header;
        g_header = g_header->next;

        printf("customer %lu, eat dataId:%d\n", pthread_self(), temp->val);
        /* 释放空间(堆上空间要释放 ) */
        delete temp;
        /* 解锁 */
        pthread_mutex_unlock(&g_mutex);
    }

    /*线程退出*/
    pthread_exit(NULL);
}

int main()
{
    /* 生成随机种子 */
    srand(time(NULL));

    /* 初始化锁 */
    pthread_mutex_init(&g_mutex, NULL);
    /* 初始化条件变量 */
    pthread_cond_init(&g_cond, NULL);

    /* 创建生产者线程 */
    pthread_t tid;
    int ret = pthread_create(&tid, NULL, thread_producer, NULL);
    if (ret != 0)
    {
        perror("thread create error:");
        exit(-1);
    }

    /* 创造消费者线程1 */
    pthread_t tid1;
    ret = pthread_create(&tid1, NULL, thread_consumer, NULL);
    if (ret != 0)
    {
        perror("thread create error:");
        exit(-1);
    }

    /*创造消费者线程2 */
    pthread_t tid2;
    ret = pthread_create(&tid2, NULL, thread_consumer, NULL);
    if (ret != 0)
    {
        perror("thread create error:");
        exit(-1);
    }


    while (1)
    {
        sleep(rand() % 3);
    }

    /* 释放锁 */
    pthread_mutex_destroy(&g_mutex);
    /* 释放条件变量 */
    pthread_cond_destroy(&g_cond);

    return 0;
}